package com.zmn.brs.starter.support.aop;

import com.zmn.brs.beans.StaffOperateRecordOps;
import com.zmn.brs.common.enums.RecordFieldEnum;
import com.zmn.brs.starter.annotation.RecordField;
import com.zmn.brs.starter.annotation.StaffOperateRecord;
import org.springframework.core.BridgeMethodResolver;
import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.util.ClassUtils;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

/**
 * 类描述：操作源数据解析
 *
 * @author xujie
 * @since 2021/03/11 17:32
 */
public class StaffOperateRecordOperationSource {

    /**
     * 员工操作记录转换
     *
     * @param method 调用注解的方法
     * @param targetClass 调用注解的类
     * @return StaffOperateRecordOps
     * @author xujie
     * @since 2021/03/11
     */
    public Collection<StaffOperateRecordOps> computeStaffOperateRecordOperations(Method method, Class<?> targetClass) {

        // 没有公共方法
        if (!Modifier.isPublic(method.getModifiers())) {
            return null;
        }
        // 方法可能在接口上，但我们需要来自目标类的属性
        // 如果目标类为null，则方法将保持不变
        Method specificMethod = ClassUtils.getMostSpecificMethod(method, targetClass);
        // 如果我们正在处理带有泛型参数的方法，请找到原始方法
        specificMethod = BridgeMethodResolver.findBridgedMethod(specificMethod);
        // 首先尝试的是目标类中的方法
        return parseStaffOperateRecordAnnotations(specificMethod);
    }

    /**
     * 解析@StaffOperateRecord
     *
     * @param ae 注释元素
     * @return StaffOperateRecordOps
     * @author xujie
     * @since 2021/03/11
     */
    private Collection<StaffOperateRecordOps> parseStaffOperateRecordAnnotations(AnnotatedElement ae) {
        
        Collection<StaffOperateRecord> staffOperateRecordAnnotationAnnotations = AnnotatedElementUtils.getAllMergedAnnotations(ae, StaffOperateRecord.class);
        Collection<StaffOperateRecordOps> ret = null;
        if (!staffOperateRecordAnnotationAnnotations.isEmpty()) {
            ret = new ArrayList<>(1);
            for (StaffOperateRecord recordAnnotation : staffOperateRecordAnnotationAnnotations) {
                ret.add(parseStaffOperateRecordAnnotation(recordAnnotation));
            }
        }
        return ret;
    }

    private StaffOperateRecordOps parseStaffOperateRecordAnnotation(StaffOperateRecord recordAnnotation) {

        RecordField[] recordFields = recordAnnotation.mapping();
        Map<String, String> recordFieldMap = new HashMap<>(recordFields.length);
        for (RecordField field : recordFields) {
            recordFieldMap.put(field.field().getField(), field.value());
        }
        return StaffOperateRecordOps.builder()
                .staffId(recordAnnotation.staffId())
                .event(recordAnnotation.event())
                .staffIp(recordFieldMap.get(RecordFieldEnum.STAFF_IP.getField()))
                .plat(recordFieldMap.get(RecordFieldEnum.PLAT.getField()))
                .unless(recordAnnotation.unless())
                .build();
    }

}
